<?php if (!defined('PmWiki')) exit();

/**	=== Attachtable Actions===
 *	Copyright 2007-2009 Eemeli Aro <eemeli@gmail.com>
 */

if ( !IsEnabled($EnableUpload,0) ) return;

## set a few values that we depend on in case upload.php hasn't been included yet
SDVA( $HandleAuth, array( 'upload' => 'upload', 'download' => 'read') );
SDV( $HandleAuth['postupload'], $HandleAuth['upload'] );

## set the default Attachtable authorization levels -- order is important for proper inheritance
SDVA( $HandleAuth, array(
	'delattach' => $HandleAuth['upload'],		# deleting a file from PmWiki while keeping it on disk
	'deldelattach' => $HandleAuth['attr'],		# deleting a file from disk
) );
SDVA( $HandleAuth, array(
	'undelattach' => $HandleAuth['delattach'],	# restoring a file
	'renameattach' => $HandleAuth['delattach']	# renaming a file
) );
SDVA( $HandleAuth, array(
	'downloaddeleted' => $HandleAuth['undelattach']	# download a deleted file
) );

SDVA( $HandleActions, array(
	'delattach' => 'HandleDeleteAttachment',
	'renameattach' => 'HandleRenameAttachment',
	'downloaddeleted' => 'HandleDownloadDeleted' ) );


include_once('attachtable-util.php');


/** Sample AttachtableLog format:
 *
	$AttachtableLogFmt = array(
		'$SiteGroup.AllRecentChanges' =>
			'* [[Attach:{$Group}/$upname]]  . . . $CurrentTime by $AuthorLink: $upreport',
		'$Group.RecentChanges' =>
			'* [[Attach:$upname]]  . . . $CurrentTime by $AuthorLink: $upreport'
	);
 */
function AttachtableLog( $pagename, $upname, $upreport ) {
	global $RecentChangesFmt, $IsPagePosted, $FmtPV, $AttachtableLogFmt;
	if (empty( $AttachtableLogFmt )) return;
	$FmtPV['$upname'] = "'$upname'";
	$FmtPV['$upreport'] = "'$upreport'";
	$rc = $RecentChangesFmt;
	$RecentChangesFmt = $AttachtableLogFmt;
	$IsPagePosted = 1;
	$p = array();
	PostRecentChanges($pagename, $p, $p);
	$IsPagePosted = 0;
	$RecentChangesFmt = $rc;
}


## action to delete attachment
## usage: ?action=delattach&upname=filename
function HandleDeleteAttachment($pagename, $auth = 'upload') {
	global $UploadFileFmt, $LastModFile, $EnableUploadVersions, $Now, $HandleAuth;

	$upname = $_REQUEST['upname'];
	if ($upname=='') Abort("?no attachment name");
	$deleted = preg_match( '/^(.*?)(,\d+)$/', $upname, $delmatch );
	$delfromdisk = $deleted || !IsEnabled($EnableUploadVersions, 0);
	if ( $delfromdisk ) $auth = $HandleAuth['deldelattach'];

	$page = RetrieveAuthPage( $pagename, $auth, true, READPAGE_CURRENT );
	if (!$page) Abort("?cannot delete attachment from $pagename");

	$upname = $deleted ?
		MakeUploadName( $pagename, $delmatch[1] ) . $delmatch[2] :
		MakeUploadName( $pagename, $upname );

	$filepath = FmtPageName("$UploadFileFmt/$upname",$pagename);
	if ( file_exists($filepath) ) {
		if ( is_dir($filepath) ) $result = 'isdir';
		else {
			$r = $delfromdisk ?
				unlink($filepath) :
				rename($filepath, "$filepath,$Now");
			if ($r) {
				if ($LastModFile) { touch($LastModFile); fixperms($LastModFile); }
				AttachtableLog( $pagename, $upname, $delfromdisk ? XL('deleted from disk') : XL('deleted') );
				$result = 'delsuccess';
			} else
				$result = $delfromdisk ? 'delfail' : 'renamefail';
		}
	} else
		$result = 'badname';

	Redirect($pagename,"{\$PageUrl}?action=upload&uprname=$upname&upresult=$result");
}


function UploadVerifyRename( $oldfilepath, $newfilepath ) {
	global $UploadExtSize;
	if ( file_exists( $newfilepath ) ) return 'upresult=exists';
	preg_match( '/\\.([^.\\/]+)$/', $newfilepath, $match ); $ext = @$match[1];
	$maxsize = $UploadExtSize[$ext];
	if ( $maxsize <= 0 ) return "upresult=badtype&upext=$ext";
	$size = filesize($oldfilepath);
	if ( $size > $maxsize ) return "upresult=toobigext&upext=$ext&upmax=$maxsize";
/* for now, can't rename across directories so no point in checking $UploadPrefixQuota or $UploadDirQuota
	global $UploadPrefixQuota;
	$filedirs = preg_replace( '#/[^/]*$#', '', array( $oldfilepath, $newfilepath ) );
	if ( $UploadPrefixQuota && ( $filedirs[0] != $filedirs[1] ) && ( ( dirsize($filedirs[1]) + $size ) > $UploadPrefixQuota ) )
		return 'upresult=pquota';
*/
	return '';
}

## action to rename attachment
## usage: ?action=renameattach&upname=filename&newname=filename
function HandleRenameAttachment($pagename, $auth = 'upload') {
	global $HandleAuth, $UploadFileFmt, $LastModFile, $TimeFmt;

	## check file
	$upname = $_REQUEST['upname'];
	if ($upname=='') Abort("?no attachment name");
	$deleted = preg_match( '/^(.*?),(\d+)$/', $upname, $delmatch );
	if ($deleted) {
		$dname = MakeUploadName( $pagename, $delmatch[1] );
		$upname = "$dname,{$delmatch[2]}";
	} else {
		$upname = MakeUploadName( $pagename, $upname );
	}
	$oldfilepath = FmtPageName( "$UploadFileFmt/$upname", $pagename );
	if ( !file_exists($oldfilepath) ) Abort("?no such attachment: $upname");
	if ( is_dir($oldfilepath) ) {
		Redirect( $pagename, "{\$PageUrl}?action=upload&uprname=$upname&upresult=isdir" );
		return;
	}

	## new name
	$newname = $_REQUEST['newname'];
	if ($newname=='') Abort("?no new attachment name<noscript> - enable JavaScript to prompt for filename or add <code>&newname=[filename]</code> to this page's URL</noscript>");
	$newname = MakeUploadName( $pagename, $newname );

	## check authorization
	if ($deleted) {
		if ( !RetrieveAuthPage( $pagename, $HandleAuth['undelattach'], TRUE, READPAGE_CURRENT ) )
			Abort("?cannot restore attachment from $pagename");
		if ( ( $dname != $newname ) && !RetrieveAuthPage( $pagename, $HandleAuth['renameattach'], TRUE, READPAGE_CURRENT ) )
			Abort("?cannot restore attachment from $pagename with a different name");
	} else {
		if ( !RetrieveAuthPage( $pagename, $HandleAuth['renameattach'], TRUE, READPAGE_CURRENT ) )
			Abort("?cannot rename attachment from $pagename");
	}

	## verify & rename
	if ($newname=='') {
		$newname = $_REQUEST['newname'];
		$result = 'upresult=badname';
	} else {
		$newfilepath = FmtPageName( "$UploadFileFmt/$newname", $pagename );
		$result = UploadVerifyRename( $oldfilepath, $newfilepath );
		if ( $result == '' ) {
			$r = rename( $oldfilepath, $newfilepath );
			if ($r) {
				if ($LastModFile) { touch($LastModFile); fixperms($LastModFile); }
				AttachtableLog( $pagename, $newname,
					$deleted ?
						XL('restored').' ('.XL('was')." $dname, ".XL('deleted').' ' . strftime( $TimeFmt, $delmatch[2] ) . ')' :
						XL('renamed').' ('.XL('was')." $upname)" );
				$result = $deleted ? 'upresult=undelsuccess' : 'upresult=renamesuccess';
			} else
				$result = 'upresult=renamefail';
		}
	}
	Redirect( $pagename, "{\$PageUrl}?action=upload&uprname=$newname&$result" );
}


## action to download deleted (ie. renamed) attachment
## usage: ?action=downloaddeleted&upname=filename,timestamp
function HandleDownloadDeleted( $pagename, $auth = 'upload' ) {
	global $UploadFileFmt, $UploadExts, $DownloadDisposition;
	SDV($DownloadDisposition, "inline");
	$upname = $_REQUEST['upname'];
	if ( !preg_match( '/^(.*?)(,\d+)$/', $upname, $delmatch ) )
		Redirect($pagename,"{\$PageUrl}?action=download&upname=$upname");
	$page = RetrieveAuthPage( $pagename, $auth, true, READPAGE_CURRENT );
	if (!$page) Abort("?cannot read $pagename");
	$upname = MakeUploadName( $pagename, $delmatch[1] ) . $delmatch[2];
	$filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
	if ( !$upname || !file_exists($filepath) ) {
		header("HTTP/1.0 404 Not Found");
		Abort("?requested file not found");
		exit();
	}
	header('Content-Type: '.AttachFiletype($filepath));
	header( "Content-Length: ".filesize($filepath) );
	header( "Content-disposition: $DownloadDisposition; filename={$delmatch[1]}" );
	$fp = fopen( $filepath, "r" );
	if ($fp) {
		while (!feof($fp)) echo fread($fp, 4096);
		fclose($fp);
	}
	exit();
}
